package com.ucode.sys.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ucode.sys.mapper.MenuMapper;
import com.ucode.sys.mapper.RoleMapper;
import com.ucode.sys.mapper.RoleMenuMapper;
import com.ucode.sys.mapper.RoleUserMapper;
import com.ucode.sys.model.Menu;
import com.ucode.sys.model.Role;
import com.ucode.sys.model.RoleMenu;
import com.ucode.sys.model.RoleUser;
import com.ucode.sys.service.RoleService;
import com.ucode.tool.base.MapVo;
import com.ucode.tool.base.Paginator;
import com.ucode.tool.util.IdentifyUtils;
import com.ucode.tool.util.ListPageModel;
import cn.hutool.core.collection.CollUtil;

@Service
public class RoleServiceImpl implements RoleService {

    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private MenuMapper menuMapper;
    @Autowired
    private RoleMenuMapper roleMenuMapper;
    @Autowired
    private RoleUserMapper roleUserMapper;
    
    @Override
    @Transactional
    public Role insert(Role role) {
        role.setId(IdentifyUtils.getDefaultSnowflakeId());
        Date now = new Date();
        role.setCreatedTime(now);
        role.setUpdatedTime(now);
        int i = roleMapper.insert(role);
        return i > 0 ? role : null;
    }

    @Override
    @Transactional
    public int update(Role role) {
        return roleMapper.update(role);
    }
    
    @Override
    public int deleteById(Long id) {
        int i = roleMapper.deleteById(id);
        List<Long> ids = Arrays.asList(id);
        roleMenuMapper.deleteByRoleId(ids);
        roleUserMapper.deleteByRoleIds(ids);
        return i;
    }

    @Override
    @Transactional
    public int delete(List<Long> ids) {
        int i = 0;
        if(CollUtil.isNotEmpty(ids)){
            i = roleMapper.delete(ids);
            roleMenuMapper.deleteByRoleId(ids);
            roleUserMapper.deleteByRoleIds(ids);
        }
        return i;
    }

    @Override
    @Transactional
    public int updateRoleMenus(Long roleId, List<Long> menuIds) {
      roleMenuMapper.deleteByRoleId(Arrays.asList(roleId));
      int count = 0;
      if(CollUtil.isNotEmpty(menuIds)){
          Date now = new Date();
          ListPageModel listPageModel = new ListPageModel(menuIds, 100);
          for (int page = 1; page <= listPageModel.getTotalPages(); page++) {
              List<Menu> menus = menuMapper.findByIds(listPageModel.getObjects(page));
              if(CollUtil.isNotEmpty(menus)){
                  List<RoleMenu> list = new ArrayList<RoleMenu>();
                  for(Menu menu : menus){
                      RoleMenu roleMenu = new RoleMenu(roleId, menu.getId(),menu.getPermission());
                      roleMenu.setId(IdentifyUtils.getDefaultSnowflakeId());
                      roleMenu.setCreatedTime(now);
                      roleMenu.setUpdatedTime(now);
                      list.add(roleMenu);
                      menuIds.add(menu.getId());
                  }
                  count = count +roleMenuMapper.batchInsert(list);
              }
          }
      }
      return count;
    }
    
    @Override
    public int relatedRoleUsers(Long roleId, List<Long> userIds) {
        int count = 0;
        if(CollUtil.isNotEmpty(userIds)){
            Date now = new Date();
            ListPageModel listPageModel = new ListPageModel(userIds, 100);
            List<RoleUser> list = null;
            for (int page = 1; page <= listPageModel.getTotalPages(); page++) {
                List<Long> pageUserIds = listPageModel.getObjects(page);
                list = new ArrayList<RoleUser>();
                for(Long userId : pageUserIds){
                    RoleUser roleUser = new RoleUser(userId, roleId);
                    roleUser.setId(IdentifyUtils.getDefaultSnowflakeId());
                    roleUser.setCreatedTime(now);
                    roleUser.setUpdatedTime(now);
                    list.add(roleUser);
                }
                
                count = count +roleUserMapper.batchInsert(list);
            }
        }
        return count;
    }
    
    @Override
    public int relatedUserRoles(Long userId, List<Long> roleIds) {
        int count = 0;
        roleUserMapper.deleteByUserId(userId);
        if(CollUtil.isNotEmpty(roleIds)){
            List<RoleUser> list = new ArrayList<RoleUser>();
            for(Long roleId : roleIds){
                RoleUser roleUser = new RoleUser(userId, roleId);
                roleUser.setId(IdentifyUtils.getDefaultSnowflakeId());
                list.add(roleUser);
            }
            count = roleUserMapper.batchInsert(list);
        }
        return count;
    }
    
    @Override
    public int unRelatedRoleUsers(Long roleId, List<Long> userIds) {
        return roleUserMapper.delete(userIds, roleId);
    }

    @Override
    public Role findById(Long id) {
        return roleMapper.findById(id);
    }
    
    @Override
    public List<Role> findByIds(List<Long> ids) {
        return roleMapper.findByIds(ids);
    }
    
    @Override
    public List<Role> findDataRoles(Long userId, Integer subSys, String permission) {
        return roleMapper.findDataRoles(userId, subSys, permission);
    }

    @Override
    public List<Role> findRolesByUserId(Long userId) {
        List<Long> roleIds = roleUserMapper.findRoleIdsByUserId(userId);
        return CollUtil.isNotEmpty(roleIds) ? roleMapper.findByIds(roleIds) : null;
    }
    
    @Override
    public List<Long> findMenuIdsByRoleId(Long roleId) {
        return roleMenuMapper.findMenuIdsByRoleId(roleId);
    }
    
    @Override
    public List<RoleMenu> findListByRoleId(Long roleId) {
        return roleMenuMapper.findListByRoleId(roleId);
    }

    @Override
    public List<RoleMenu> findListByRoleIds(List<Long> roleIds) {
        return roleMenuMapper.findListByRoleIds(roleIds);
    }
    
    @Override
    public List<MapVo<Long, String>> findUserRoleNames(List<Long> userIds) {
        return roleUserMapper.findUserRoleNames(userIds);
    }

    @Override
    public Paginator<Role> queryPage(Integer subSys,String name, int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<Role> roles = roleMapper.queryList(subSys,name);
        PageInfo<Role> pageInfo = new PageInfo<>(roles);
        return new Paginator<>(pageInfo.getTotal(), pageInfo.getPageNum(), pageInfo.getPageSize(), roles);
    }
}
